﻿function Install-SharePointPostPrereqHotfixes
{
    <# 
     .Synopsis
        Installs hotfixes required for SharePoint but not included in the SharePoint Prerequisite Installer

     .Description
        This script executes unattended installations for each of the hotfixes required by SharePoint but not included in the SharePoint Prerequisite installer. The script will detect the underlying OS Version and select the hotfixes that are appropriate. The following hotfixes will be installed by this script:
        
        For SharePoint 2013
            Both Windows Server 2008 R2 SP1 and Windows Server 2012
                Hotfix 1:
                ASP.NET (SharePoint) race condition in .NET 4.5 RTM
                http://go.microsoft.com/fwlink/p/?LinkId=267536
        
            Windows Server 2008 R2 SP1 Only
                Hotfix 2:
                The SharePoint parsing process crashes in Windows Server 2008 R2 (KB 2554876)
                http://go.microsoft.com/fwlink/p/?LinkId=258850

                Hotfix 3:
                IIS 7.5 configurations are not updated when you use the ServerManager class to commit configuration changes (KB 2708075)
                http://go.microsoft.com/fwlink/p/?LinkId=258851

        For SharePoint 2010
                <NOT CURRENTLY IMPLEMENTED>       

     .Parameter Ws2012InstallFiles
        The full file system path where the installation source files for the Windows Server 2012 hotfixes are located.
        The default value for this parameter is '$env:ProgramData\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\WS2012'

     .Parameter W2K8R2Sp1InstallFiles
        The full file system path where the installation source files for the Windows Server 2008 R2 SP1 hotfixes are located.
        The default value for this parameter is '$env:ProgramData\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\W2K8R2Sp1'

     .Parameter CommonInstallFiles
        The full file system path where the installation source files common to all target operating system hotfixes are located.
        The default value for this parameter is '$env:ProgramData\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\Common'

     .Parameter SharePointVersion
        Use this parameter to indicate which SharePoint Version to install. Valid choices are '2010' and '2013'

     .Example
        Install-SharePointPostPrereqHotfixes

        # If using the default file path and installing for SharePoint 2013

     .Example
        Install-SharePointPostPrereqHotfixes -SharePointVersion 2013 -PathToInstallFiles 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\'

        # If using a custom location for the installation files default configuration file path and structure, provide discrete paramaters to each subdirectory

    #>
    [CmdletBinding(DefaultParametersetName="CustomPaths")]
    param([parameter(ParameterSetName = "CustomPaths", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files for the Windows Server 2012 hotfixes are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\WS2012'")]
                     [string]$Ws2012InstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\WS2012"),
	      [parameter(ParameterSetName = "CustomPaths", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files for the Windows Server 2008 R2 SP1 hotfixes are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\W2K8R2Sp1'")]
                     [string]$W2K8R2Sp1InstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\W2K8R2Sp1"),
	      [parameter(ParameterSetName = "CustomPaths", 
                     Mandatory = $false,
                     HelpMessage = "The full file system path where the installation source files common to all target operating system hotfixes are located. The default value for this parameter is 'C:\ProgramData\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\Common'")]
                     [string]$CommonInstallFiles = ($env:ProgramData + "\SharePoint Total Automation Toolkit\Software\02-PostPrereqHotfixes\Common"),
          [parameter(ParameterSetName = "CustomPaths",
                     Mandatory = $false,
                     HelpMessage = "Use this parameter to indicate which SharePoint Version to install. Valid choices are '2010' and '2013'")]
                     [ValidateSet ("2010","2013")]
                     [string]$SharePointVersion = "2013")

    switch ($PSCmdlet.ParameterSetName)
    {
        "CustomPaths"
        {
        }    
    }

	$rebootStatus = Get-PendingReboot
	if ($rebootStatus.RebootPending -eq $true)
	{
		Write-Host "NOTE: A system restart is required. Please restart the system prior to continuing with the hotfix installation." -ForegroundColor Yellow
		Write-Host "      When the system restarts please rerun this script until you no longer receive a restart request." -ForegroundColor Yellow
		throw 
	}

    # Initialize Progress Variables
    [int]$progressNumPhases = 1
    [int]$progressNumPhasesComplete = 0
    [int]$progressCurrentTask = 0
    [int]$progressTotalTasks = 0
    [int]$progressTotal = 0
    [int]$progressBarId = 100
    $startTime = [System.DateTime]::Now

    # First determine which OS we are installing on
    $osVersionMajor = [System.Environment]::OSVersion.Version.Major
    $osVersionMinor = [System.Environment]::OSVersion.Version.Minor

    If ($SharePointVersion -eq "2013")
    {
        Write-Host
        Write-Host "Beginning the SharePoint 2013 Post Prerequisite Hotfix Software Installation."

        # If we are installing on Windows Server 2012 R2
        if (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 3))
        {
			write-Host "     No updates necessary." -ForegroundColor Yellow
		}
        # If we are installing on Windows Server 2012
        elseif (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 2))
        {    
		    # Initialize the progress variables for the current phase
		    $progressCurrentTask = 0
		    $progressTotalTasks = 1

            #region Task 1

            # Hotfix 1:
            # ASP.NET (SharePoint) race condition in .NET 4.5 RTM
            # http://go.microsoft.com/fwlink/p/?LinkId=267536
            $hotfixFile = "Windows8-RT-KB2765317-x64.msu"
            $setupExe = "wusa.exe"
            $setupArgs = ('"' + $Ws2012InstallFiles + '\' + $hotfixFile + '"') + ' /quiet /norestart'

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint 2013 Post Prerequisite Hotfixes" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Hotfix successfully installed ($hotfixFile)"        
            }
            elseif ($setupExeInstance.ExitCode -eq 2359302)
            {
                Write-Host "     Hotfix already installed ($hotfixFile)" -ForegroundColor Yellow
            }
            else 
            {
				$exitCode = $setupExeInstance.ExitCode
                Write-Error "     Installation of hotfix ($hotfixFile) failed with exit code ($exitCode)"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion
        }
        # If we are installing on Windows Server 2008 R2
        elseif (($osVersionMajor -eq 6) -and ($osVersionMinor -eq 1))
        {
		    # Initialize the progress variables for the current phase
		    $progressCurrentTask = 0
		    $progressTotalTasks = 3

            #region Task 1

            # Hotfix 1:
            # ASP.NET (SharePoint) race condition in .NET 4.5 RTM
            # http://go.microsoft.com/fwlink/p/?LinkId=267536
            $hotfixFile = "NDP45-KB2759112-x64.exe"
            $setupExe = ('"' + $W2K8R2Sp1InstallFiles + '\' + $hotfixFile +'"')
            $setupArgs = "/passive /norestart"

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint 2013 Post Prerequisite Hotfixes" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Hotfix successfully installed ($hotfixFile)"        
            }
            else 
            {
				$exitCode = $setupExeInstance.ExitCode
                Write-Error "     Installation of hotfix ($hotfixFile) failed with exit code ($exitCode)"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete

            #endregion

            #region Task 2

            # Hotfix 2:
            # The SharePoint parsing process crashes in Windows Server 2008 R2 (KB 2554876)
            # http://go.microsoft.com/fwlink/p/?LinkId=258850
            $hotfixFile = "Windows6.1-KB2554876-v2-x64.msu"
            $setupExe = "wusa.exe"
            $setupArgs = ('"' + $W2K8R2Sp1InstallFiles + '\' + $hotfixFile + '"') + ' /quiet /norestart'

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint 2013 Post Prerequisite Hotfixes" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Hotfix successfully installed ($hotfixFile)"        
            }
            else 
            {
				$exitCode = $setupExeInstance.ExitCode
                Write-Error "     Installation of hotfix ($hotfixFile) failed with exit code ($exitCode)"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete
        
            #endregion

            #region Task 3

            # Hotfix 3:
            # IIS 7.5 configurations are not updated when you use the ServerManager class to commit configuration changes (KB 2708075)
            # http://go.microsoft.com/fwlink/p/?LinkId=258851
            $hotfixFile = ($W2K8R2Sp1InstallFiles + "\Windows6.1-KB2708075-x64.msu")
            $hotfixFile = "Windows6.1-KB2708075-x64.msu"
            $setupExe = "wusa.exe"
            $setupArgs = ('"' + $W2K8R2Sp1InstallFiles + '\' + $hotfixFile + '"') + ' /quiet /norestart'

            $setupExeInstance = [System.Diagnostics.Process]::Start($setupExe, $setupArgs)

            while (-not ($setupExeInstance.HasExited)){
                $currentRuntime = [System.DateTime]::Now - $startTime
                Write-Progress -Id $progressBarId -Activity "Installing SharePoint 2013 Post Prerequisite Hotfixes" -PercentComplete $progressTotal -CurrentOperation ("Installing hotfix - " + $hotfixFile) -Status ("The current operation has been running for {0}:{1}:{2}" -f $currentRuntime.Hours.ToString("00"), $currentRuntime.Minutes.ToString("00"), $currentRuntime.Seconds.ToString("00"))

                Start-Sleep -Seconds 1
            }

            if ($setupExeInstance.ExitCode -eq 0)
            {
                Write-Host "     Hotfix successfully installed ($hotfixFile)"        
            }
            else 
            {
				$exitCode = $setupExeInstance.ExitCode
                Write-Error "     Installation of hotfix ($hotfixFile) failed with exit code ($exitCode)"
                throw
            }

		    # Increment the progress variables for the current task
		    $progressCurrentTask++
		    $progressTotal = CalculateProgress $progressCurrentTask $progressTotalTasks $progressNumPhases $progressNumPhasesComplete

            #endregion
        }

        # Increment the Phase Completion Counter
        $progressNumPhasesComplete++

        Write-Progress -Id $progressBarId -Activity "Installing SharePoint 2013 Post Prerequisite Hotfixes" -Status "Finishing" -PercentComplete 100 -CurrentOperation "" -Completed

        Write-Host "SharePoint 2013 Post Prerequisite Hotfix Software Installation Complete."
    }
    elseif ($SharePointVersion -eq "2010")
    {
        throw "SharePoint 2010 updates have not yet been implemented. Please manually install any required hotfixes."
    }
}